<?php
namespace tp5_lib\account\logic;

use tp5_lib\common\logic\Logic;
use tp5_lib\account\model\AccountLogModel;
use tp5_lib\user\model\UserModel;
use think\Db;
use think\db\Query;
use tp5_lib\account\model\WithdrawModel;
use tp5_lib\bankcard\model\BankcardModel;
use tp5_lib\account\extension\PaymentMethod;
use tp5_lib\account\extension\PaymentTrade;

class AccountLogic extends Logic
{
    /**
     * 获取余额
     * @param string $id 用户ID
     * @return float
     */
    public function surplus($id)
    {
        $model=new UserModel();
        if(!$user=$model->db()->where(["id"=>$id])->find()){
            $this->error="用户不存在";
            return false;
        }
        return $model["money"];
    }
    public function change($handler,$uid,$amount,$message)
    {
        $user_model=new UserModel();
        $log_model=new AccountLogModel();
        /** @var Query $db */
        $db=Db::connect();
        $db->startTrans();
        try {
            $sql=$user_model->db()->where(["id"=>$uid])->fetchSql()->find();
            if(!$set=$db->query($sql)){
                $db->rollback();
                $this->error="用户不存在";
                return false;
            }
            $user=$set[0];
            
            $data=[
                "handler"=>$handler,
                "user_id"=>$uid,
                "previous"=>$user["money"],
                "money"=>$amount,
                "message"=>$message,
                "time"=>time(),
            ];
            $sql=$log_model->db()->fetchSql()->insert($data);
            if(!$db->execute($sql)){
                $db->rollback();
                $this->error="插入记录失败";
                return false;
            }

            $sql=$user_model->where(["id"=>$uid])->fetchSql()->setInc("money",$amount);
            if(!$db->execute($sql)){
                $db->rollback();
                $this->error="修改余额失败";
                return false;
            }

            $db->commit();
            
        } catch (\Exception $th) {
            $db->rollback();
            $this->error="数据库错误";
            return false;
        }
        
        return true;
    }
    /**
     * 批量修改账户
     * 需要确保数据正确，否则整个事务无法提交
     * @param string $handler 操作者编号
     * @param array[] $list 参数列表
     *  例如:[["uid"=>"1","amount"=>1.00,"message"=>"充值"]]
     */
    public function batch($handler,$list)
    {
        $user_model=new UserModel();
        $log_model=new AccountLogModel();
        /** @var Query $db */
        $db=Db::connect();
        $db->startTrans();
        $time=time();
        try {
            foreach($list as $item){
                $user=$user_model->db()->where(["id"=>$item["uid"]])->find();
                $data=[
                    "handler"=>$handler,
                    "user_id"=>$item["uid"],
                    "previous"=>$user["money"],
                    "money"=>$item["amount"],
                    "type"=>$item["type"],
                    "asso_id"=>$item["asso_id"],
                    "message"=>$item["message"],
                    "time"=>$time,
                ];
                $log_model->db()->insert($data);
                $user_model->where(["id"=>$item["uid"]])->setInc("money",$item["amount"]);
            }
            $db->commit();
        }
        catch (\Exception $th) {
            $db->rollback();
            $this->error="数据库错误";
            return false;
        }
        return true;
    }
    /**
     * 根据订单号获取处理方法和ID
     */
    protected function parseTrade($no)
    {
        list($type,$id)=explode("-",$no);
        if($type === "recharge") return [new RechargeLogic,$id];
        
        $module=new AccountModule();
        if(!$config=$module->read("account")){
            $this->error("配置文件丢失");
        }
        foreach($config["trade"] as $trade => $params){
            if($type === $trade){
                $class=$params["class"];
                return [new $class,$id];
            }
        }
        $this->error="未定义的交易类型";
        return false;
    }
    /**
     * 交易成功
     */
    public function success($no)
    {
        /** @var PaymentTrade $logic */
        list($logic,$id)=$this->parseTrade($no);
        if(!$result = $logic->paySuccess($id)) $this->error="Recharge:".$logic->getError();
        return $result;
    }
    /**
     * 交易关闭
     */
    public function close($no)
    {
        /** @var PaymentTrade $logic */
        list($logic,$id)=$this->parseTrade($no);
        if(!$result = $logic->payClose($id)) $this->error="Recharge:".$logic->getError();
        return $result;
    }
    /**
     * 查看状态
     */
    public function status($no)
    {
        /** @var PaymentTrade $logic */
        list($logic,$id)=$this->parseTrade($no);
        if(!$result = $logic->payStatus($id)) $this->error="Recharge:".$logic->getError();
        return $result;
    }
    public function precreate($way,$type,$id,$amount,$title,$content="")
    {
        $module=new AccountModule();
        if(!$config=$module->read("account")){
            $this->error("配置文件丢失");
        }
        if(empty($config["payment"][$way])){
            $this->error("未定义的支付方式");
        }
        $payment=$config["payment"][$way];
        $class=$payment["class"];
        /** @var PaymentMethod $object */
        $object=new $class;
        return $object->precreate("$type-$id",$amount,$title,$content);
    }
    /**
     * 提现
     * 创建交易记录并且将余额扣掉
     * @param string $uid 用户ID
     */
    public function withdraw($uid,$amount,$way)
    {
        $user_model=new UserModel();
        $log_model=new AccountLogModel();
        $model=new WithdrawModel();
        /** @var Query $db */
        $db=Db::connect();
        $db->startTrans();
        try {
            $user=$user_model->db()->where(["id"=>$uid])->find();
            if(floatval($user["money"]) < floatval($amount)){
                $this->error="余额不足";
                return false;
            }

            $sql=$model->db()->fetchSql()->insertGetId([
                "user_id"=>$uid,
                "amount"=>$amount,
                "time"=>time(),
                "way"=>$way,
                "account"=>"",
            ]);
            if(!$db->execute($sql)){
                $this->error="创建失败";
                return false;
            }
            if(!$id=$db->getLastInsID()){
                $this->error="无法获取插入的ID";
                return false;
            }

            $sql=$log_model->db()->fetchSql()->insert([
                "handler"=>0,
                "user_id"=>$uid,
                "previous"=>$user["money"],
                "money"=>$amount,
                "type"=>"withdraw",
                "asso_id"=>$id,
                "message"=>"用户申请提现",
                "time"=>time(),
            ]);
            if(!$db->execute($sql)){
                $db->rollback();
                $this->error="插入记录失败";
                return false;
            }

            $sql=$user_model->where(["id"=>$uid])->fetchSql()->setDec("money",$amount);
            if(!$db->execute($sql)){
                $this->error="修改余额失败";
                return false;
            }
            $db->commit();
            return true;
        }
        catch (\Exception $ex) {
            $db->rollback();
            $this->error="数据库操作错误:".$ex->getMessage();
            return false;
        }
    }
    /**
     * 管理员确认提现完成
     */
    public function doWithdraw($id,$handler)
    {
        $model=new WithdrawModel();
        if(!$record=$model->db()->where(["id"=>$id])->find()){
            $this->error="记录不存在";
            return false;
        }
        if(!$model->db()->where(["id"=>$id])->setField("status",1)){
            $this->error="修改记录失败";
            return false;
        }
        return true;
    }
    /**
     * 取消提现
     * 退回订单中的金额
     */
    public function cancelWithdraw($id,$handler)
    {
        $model=new WithdrawModel();
        if(!$record=$model->db()->where(["id"=>$id])->find()){
            $this->error="记录不存在";
            return false;
        }
        if(!$model->db()->where(["id"=>$id])->setField("status",2)){
            $this->error="修改记录失败";
            return false;
        }
        if(!$this->change($handler,$record["user_id"],$record["amount"],"提现($id)失败，退回金额")){
            $this->error="修改账户失败";
            return false;
        }
        return true;
    }
    /**
     * 是否已绑定提现方式
     */
    public function hasWithdrawWay($user)
    {
        if(!empty($user["alipay"]) || !empty($user["wxpay"])){
            return true;
        }
        $bankcard_model=new BankcardModel();
        if($bankcard_model->where(["user_id"=>$user["id"]])->find()){
            return true;
        }
        return false;
    }
}
